/**************************************************************************//**
\file  pv.c

\brief This module is used for measure PV value.

\author
	Satxo

\internal
  History:
    29/06/07 R. Rodrigues - Created
******************************************************************************/
/******************************************************************************
                   Includes section
******************************************************************************/
#include <pv.h>
#include <bspadc.h>
#include <appTimer.h>
#include <bspTaskManager.h>
#include <types.h>
#include <gpio.h>

/******************************************************************************
                   Define(s) section
******************************************************************************/

#define PV_DELAY						10	// in milliseconds

#define PV_STATE_QUEUE_LEN				8	// state queue length

/******************************************************************************
                   Global variables section
******************************************************************************/
// The flow control variable
static PVControl_t pvControl;

// hods a FIFO queue of task for the bspHIH5031Handler task handler function
static PVStates_t pvState[PV_STATE_QUEUE_LEN] = { PV_IDLE };

// Timer structure, used to make the delays needed for A2D conversion
static HAL_AppTimer_t pvDelay;

uint16_t value; // Auxiliary measure

/******************************************************************************
                   Implementations section
******************************************************************************/
/**************************************************************************//**
\brief  Adds a new task to the task queue, FIFO style.

\param[in]
  task - the task to be queued.

\return
  BC_FAIL - if the queue if full, has more than PV_STATE_QUEUE_LEN tasks
  BC_SUCCESS - other case.

******************************************************************************/
result_t pvPushTask(PVStates_t task)
{	
	uint8_t i;
	for( i=0; i < PV_STATE_QUEUE_LEN-1; i++)
	{
		/* the queue is filled with IDLE tasks by default.
		The first IDLE task found will be replaced by the task we want to add. */
		if( pvState[i] == PV_IDLE )
		{
			pvState[i] = task;
			return BC_SUCCESS;
		}
	}
	return BC_FAIL;
}

/**************************************************************************//**
\brief	Returns the first task to be executed from the queue, FIFO style.

\return
	the task in queue to be executed.
******************************************************************************/
PVStates_t pvPopTask(void)
{	
	uint8_t i;
	PVStates_t task = pvState[0];
	
	for( i=0; i < PV_STATE_QUEUE_LEN-1; i++)
	{
		pvState[i] = pvState[i+1];
	}
	return task;
}


/**************************************************************************//**
\brief  Opens the component to use.

\return
  BC_SUCCESS - the component is ready to been use.
  BC_FAIL - otherwise.

******************************************************************************/
result_t openPV(void)
{
	if (PV_IDLE == pvState[0])
	{
	    return BC_SUCCESS;
	}
		
	return BC_FAIL;
}


/**************************************************************************//**
\brief  Performs the test if the component have completed request.

\return
  BC_FAIL - the previous request is not completed.
  BC_SUCCESS - otherwise.
******************************************************************************/
result_t closePV(void)
{
  if (PV_IDLE == pvState[0])
  {
		return BC_SUCCESS;
  }	

  return BC_FAIL;
}

/**************************************************************************//**
\brief Reads data from PV sensor.

\param[in]
  f - callback method.
\param[in]
  result - the result of the requested operation.
           true - operation finished successfully,
           false - some error has occurred.
\param[in]
  data - sensor data.
\return
  BC_FAIL - the previous request was not completed.
  BC_SUCCESS - other case.
******************************************************************************/
result_t readPVData(void (*f)(bool result, uint16_t data))
{	
	if (PV_IDLE != pvState[0])
		return BC_FAIL;

	if (!f)
		return BC_FAIL;
		
	pvControl.pvCallback = f;

	if (BC_FAIL == pvPushTask(PV_WAIT))
		return BC_FAIL;
	if (BC_FAIL == pvPushTask(PV_GET_PV))
		return BC_FAIL;
	if (BC_FAIL == pvPushTask(PV_RETURN))
		return BC_FAIL;
	bspPostTask(BSP_PV);
	
	return BC_SUCCESS;
}

/**************************************************************************//**
\brief  Starts ADC request on pv channel. XXXXXXXXXXXX
******************************************************************************/
void pvDataCallback(uint16_t data)
{
	pvControl.pvData = data;
	if (data == 0)
		pvControl.pvResult = false;
	else
		pvControl.pvResult = true;
	bspPostTask(BSP_PV);
}

/**************************************************************************//**
\brief PV Task Handler.
******************************************************************************/
void bspPVHandler(void)
{
	PVStates_t task;
	task = pvPopTask();

	if (task ==	PV_IDLE)
	{	// IDLE state, does nothing
		return;
	}

	if (task ==	PV_RETURN)
	{	// if queue is empty, call top layer task handler, else continue to next task
		if (PV_IDLE == pvState[0])
			pvControl.pvCallback(pvControl.pvResult, pvControl.pvData);
		else
			bspPostTask(BSP_PV);

		return;
	} // RETURN

	if (task ==	PV_WAIT)
	{	// wait PV_WAIT milliseconds to jump to the next task
		pvDelay.interval = PV_DELAY;					// Timer interval in milliseconds
		pvDelay.mode     = TIMER_ONE_SHOT_MODE;			// One shot mode (TIMER_REPEAT_MODE or TIMER_ONE_SHOT_MODE)
		pvDelay.callback = bspPVHandler;				// Callback function for timer fire event
		HAL_StartAppTimer(&pvDelay);
		return;
	} // WAIT

	if (task ==	PV_GET_PV)
	{		
		readBspAdc(pvDataCallback, BSP_ADC_CHANNEL3);
		return;
	} // PV_GET_PV

}

// eof pv.c
